package com.example.xunai.controller;

import com.example.xunai.dto.request.ai.ChatRequest;
import com.example.xunai.dto.request.ai.StreamChatRequest;
import com.example.xunai.dto.request.conversation.CreateConversationRequest;
import com.example.xunai.dto.request.conversation.UpdateConversationRequest;
import com.example.xunai.dto.response.conversation.ConversationResponse;
import com.example.xunai.dto.response.conversation.ConversationListResponse;
import com.example.xunai.dto.response.conversation.MessageResponse;
import com.example.xunai.dto.response.system.ApiResponse;
import com.example.xunai.entity.User;
import com.example.xunai.service.ai.AiChatService;
import com.example.xunai.service.conversation.ConversationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import jakarta.servlet.http.HttpSession;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@RestController
@RequestMapping("/api/conversations")
@RequiredArgsConstructor
public class ConversationController {

    private final ConversationService conversationService;
    private final AiChatService aiChatService;

    // 存储活跃的请求ID，防止重复请求
    private final Map<String, Long> activeRequests = new ConcurrentHashMap<>();
    private static final long REQUEST_TIMEOUT = 120000; // 2分钟

    // 获取当前用户的所有对话 - 使用新的Response对象
    @GetMapping
    public ResponseEntity<ApiResponse<ConversationListResponse>> getConversations(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "20") Integer size,
            HttpSession session) {

        User user = (User) session.getAttribute("user");
        if (user == null) {
            return ResponseEntity.status(401).body(ApiResponse.error("401", "未登录"));
        }

        try {
            ConversationListResponse conversations = conversationService.getUserConversationsResponse(user.getId(), page, size);
            return ResponseEntity.ok(ApiResponse.success(conversations));
        } catch (Exception e) {
            log.error("获取对话列表失败", e);
            return ResponseEntity.status(500).body(ApiResponse.error("500", "获取对话列表失败"));
        }
    }

    // 清空所有对话
    @DeleteMapping("/clear-all")
    public ResponseEntity<ApiResponse<Object>> clearAllConversations(HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) {
            return ResponseEntity.status(401).body(ApiResponse.error("401", "未登录"));
        }

        try {
            // 获取用户所有对话并逐个删除
            ConversationListResponse conversations = conversationService.getUserConversationsResponse(user.getId(), 1, 1000);
            int deletedCount = 0;

            for (ConversationResponse conversation : conversations.getConversations()) {
                try {
                    conversationService.deleteConversation(user.getId(), conversation.getId());
                    deletedCount++;
                } catch (Exception e) {
                    log.warn("删除对话失败，对话ID: {}, 错误: {}", conversation.getId(), e.getMessage());
                }
            }

            log.info("成功清空用户所有对话，用户ID: {}, 删除对话数量: {}", user.getId(), deletedCount);
            return ResponseEntity.ok(ApiResponse.success("所有对话已清空", Map.of("deletedCount", deletedCount)));
        } catch (Exception e) {
            log.error("清空所有对话失败，用户ID: {}", user.getId(), e);
            return ResponseEntity.status(500).body(ApiResponse.error("500", "清空失败: " + e.getMessage()));
        }
    }

    // 创建新对话 - 使用新的Request对象
    @PostMapping
    public ResponseEntity<ApiResponse<ConversationResponse>> createConversation(
            @RequestBody CreateConversationRequest request,
            HttpSession session) {

        User user = (User) session.getAttribute("user");
        if (user == null) {
            return ResponseEntity.status(401).body(ApiResponse.error("401", "未登录"));
        }

        try {
            // 设置用户ID
            request.setUserId(user.getId());

            // 生成会话ID
            String sessionId = generateSessionId();
            request.setSessionId(sessionId);

            ConversationResponse conversation = conversationService.createConversation(request);
            return ResponseEntity.ok(ApiResponse.success(conversation));
        } catch (Exception e) {
            log.error("创建对话失败", e);
            return ResponseEntity.status(500).body(ApiResponse.error("500", "创建对话失败: " + e.getMessage()));
        }
    }

    // 获取单个对话详情 - 使用新的Response对象
    @GetMapping("/{id}")
    public ResponseEntity<ApiResponse<ConversationResponse>> getConversation(
            @PathVariable Long id,
            HttpSession session) {

        User user = (User) session.getAttribute("user");
        if (user == null) {
            return ResponseEntity.status(401).body(ApiResponse.error("401", "未登录"));
        }

        try {
            ConversationResponse conversation = conversationService.getConversationResponseById(user.getId(), id);
            if (conversation != null) {
                return ResponseEntity.ok(ApiResponse.success(conversation));
            } else {
                return ResponseEntity.status(404).body(ApiResponse.error("404", "对话不存在"));
            }
        } catch (Exception e) {
            log.error("获取对话详情失败", e);
            return ResponseEntity.status(500).body(ApiResponse.error("500", "获取对话详情失败"));
        }
    }

    // 获取对话的所有消息 - 使用新的Response对象
    @GetMapping("/{conversationId}/messages")
    public ResponseEntity<ApiResponse<List<MessageResponse>>> getConversationMessages(
            @PathVariable Long conversationId,
            HttpSession session) {

        User user = (User) session.getAttribute("user");
        if (user == null) {
            return ResponseEntity.status(401).body(ApiResponse.error("401", "未登录"));
        }

        try {
            List<MessageResponse> messages = conversationService.getConversationMessageResponses(user.getId(), conversationId);
            return ResponseEntity.ok(ApiResponse.success(messages));
        } catch (RuntimeException e) {
            return ResponseEntity.status(404).body(ApiResponse.error("404", e.getMessage()));
        } catch (Exception e) {
            log.error("获取对话消息失败", e);
            return ResponseEntity.status(500).body(ApiResponse.error("500", "获取对话消息失败"));
        }
    }

    /**
     * 对话流式聊天接口
     */
    @GetMapping(value = "/{conversationId}/chat/stream", produces = "text/event-stream")
    public SseEmitter streamConversationChat(
            @PathVariable Long conversationId,
            @RequestParam String message,
            @RequestParam String sessionId,
            @RequestParam(defaultValue = "deepseek") String modelType,
            @RequestParam(required = false) String requestId,
            HttpSession session) {

        User user = (User) session.getAttribute("user");
        if (user == null) {
            throw new RuntimeException("未登录");
        }

        // 生成或使用传入的请求ID
        String finalRequestId = (requestId != null && !requestId.trim().isEmpty()) ?
                requestId : generateRequestId();

        // 检查重复请求
        if (isDuplicateRequest(finalRequestId)) {
            log.warn("检测到重复请求，请求ID: {}, 用户ID: {}, 会话ID: {}",
                    finalRequestId, user.getId(), sessionId);
            SseEmitter emitter = new SseEmitter();
            emitter.completeWithError(new RuntimeException("重复请求，请稍后再试"));
            return emitter;
        }

        // 记录活跃请求
        activeRequests.put(finalRequestId, System.currentTimeMillis());

        log.info("处理对话流式请求，模型: {}, 用户ID: {}, 会话ID: {}, 对话ID: {}, 消息长度: {}, 请求ID: {}",
                modelType, user.getId(), sessionId, conversationId, message.length(), finalRequestId);

        // 创建StreamChatRequest并调用AiChatService
        StreamChatRequest request = StreamChatRequest.of(message, sessionId, conversationId, user.getId(), modelType, finalRequestId);
        SseEmitter emitter = aiChatService.streamChat(request);

        // 设置完成回调，清理活跃请求
        emitter.onCompletion(() -> {
            activeRequests.remove(finalRequestId);
            log.info("请求完成，清理活跃请求: {}", finalRequestId);
        });

        emitter.onTimeout(() -> {
            activeRequests.remove(finalRequestId);
            log.warn("请求超时，清理活跃请求: {}", finalRequestId);
        });

        emitter.onError((error) -> {
            activeRequests.remove(finalRequestId);
            log.error("请求错误，清理活跃请求: {}, 错误: {}", finalRequestId, error.getMessage());
        });

        return emitter;
    }

    /**
     * 停止生成接口
     */
    @PostMapping("/stop")
    public ResponseEntity<ApiResponse<Object>> stopGeneration(@RequestBody StopRequest request, HttpSession session) {
        User user = (User) session.getAttribute("user");
        if (user == null) {
            return ResponseEntity.status(401).body(ApiResponse.error("401", "未登录"));
        }

        log.info("收到停止请求，用户ID: {}, 会话ID: {}, 对话ID: {}, 请求ID: {}",
                user.getId(), request.getSessionId(), request.getConversationId(), request.getRequestId());

        try {
            // 直接调用停止方法
            aiChatService.setStreamStopFlag(request.getSessionId());

            // 如果有请求ID，清理活跃请求
            if (request.getRequestId() != null) {
                activeRequests.remove(request.getRequestId());
            }

            return ResponseEntity.ok(ApiResponse.success("停止请求已发送"));
        } catch (Exception e) {
            log.error("处理停止请求失败", e);
            return ResponseEntity.status(500).body(ApiResponse.error("500", "停止失败: " + e.getMessage()));
        }
    }

    // 更新对话标题 - 使用新的Request对象
    @PutMapping("/{conversationId}/title")
    public ResponseEntity<ApiResponse<ConversationResponse>> updateConversationTitle(
            @PathVariable Long conversationId,
            @RequestBody UpdateTitleRequest request,
            HttpSession session) {

        User user = (User) session.getAttribute("user");
        if (user == null) {
            return ResponseEntity.status(401).body(ApiResponse.error("401", "未登录"));
        }

        try {
            UpdateConversationRequest updateRequest = UpdateConversationRequest.withTitle(request.getTitle());
            ConversationResponse updatedConversation = conversationService.updateConversation(conversationId, updateRequest);
            return ResponseEntity.ok(ApiResponse.success(updatedConversation));
        } catch (RuntimeException e) {
            return ResponseEntity.status(404).body(ApiResponse.error("404", e.getMessage()));
        } catch (Exception e) {
            log.error("更新对话标题失败", e);
            return ResponseEntity.status(500).body(ApiResponse.error("500", "更新对话标题失败"));
        }
    }

    // 更新对话模型（仅在对话没有消息时允许）- 使用新的Request对象
    @PutMapping("/{conversationId}/model")
    public ResponseEntity<ApiResponse<ConversationResponse>> updateConversationModel(
            @PathVariable Long conversationId,
            @RequestBody UpdateModelRequest request,
            HttpSession session) {

        User user = (User) session.getAttribute("user");
        if (user == null) {
            return ResponseEntity.status(401).body(ApiResponse.error("401", "未登录"));
        }

        try {
            UpdateConversationRequest updateRequest = UpdateConversationRequest.withModel(request.getModel());
            ConversationResponse updatedConversation = conversationService.updateConversation(conversationId, updateRequest);
            return ResponseEntity.ok(ApiResponse.success(updatedConversation));
        } catch (RuntimeException e) {
            return ResponseEntity.status(404).body(ApiResponse.error("404", e.getMessage()));
        } catch (Exception e) {
            log.error("更新对话模型失败", e);
            return ResponseEntity.status(500).body(ApiResponse.error("500", "更新对话模型失败: " + e.getMessage()));
        }
    }

    // 删除对话
    @DeleteMapping("/{conversationId}")
    public ResponseEntity<ApiResponse<Object>> deleteConversation(
            @PathVariable Long conversationId,
            HttpSession session) {

        User user = (User) session.getAttribute("user");
        if (user == null) {
            return ResponseEntity.status(401).body(ApiResponse.error("401", "未登录"));
        }

        try {
            conversationService.deleteConversation(user.getId(), conversationId);
            return ResponseEntity.ok(ApiResponse.success("对话删除成功"));
        } catch (RuntimeException e) {
            return ResponseEntity.status(404).body(ApiResponse.error("404", e.getMessage()));
        } catch (Exception e) {
            log.error("删除对话失败", e);
            return ResponseEntity.status(500).body(ApiResponse.error("500", "删除对话失败"));
        }
    }

    // 生成随机会话ID
    private String generateSessionId() {
        return "sess_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8);
    }

    // 生成请求ID
    private String generateRequestId() {
        return "req_" + System.currentTimeMillis() + "_" +
                UUID.randomUUID().toString().substring(0, 8);
    }

    // 检查重复请求
    private boolean isDuplicateRequest(String requestId) {
        // 清理过期的请求
        cleanExpiredRequests();

        // 检查是否存在相同的请求ID
        return activeRequests.containsKey(requestId);
    }

    // 清理过期的请求
    private void cleanExpiredRequests() {
        long currentTime = System.currentTimeMillis();
        activeRequests.entrySet().removeIf(entry ->
                (currentTime - entry.getValue()) > REQUEST_TIMEOUT
        );
    }

    public static class UpdateTitleRequest {
        private String title;
        public String getTitle() { return title; }
        public void setTitle(String title) { this.title = title; }
    }

    public static class UpdateModelRequest {
        private String model;
        public String getModel() { return model; }
        public void setModel(String model) { this.model = model; }
    }

    public static class StopRequest {
        private String sessionId;
        private Long conversationId;
        private String requestId;

        public String getSessionId() { return sessionId; }
        public void setSessionId(String sessionId) { this.sessionId = sessionId; }
        public Long getConversationId() { return conversationId; }
        public void setConversationId(Long conversationId) { this.conversationId = conversationId; }
        public String getRequestId() { return requestId; }
        public void setRequestId(String requestId) { this.requestId = requestId; }
    }
}